/**
 * 多屏相机同步
 *
 * @param    viewers  需要同步的viewers数组,示例：[{id: dom的id， viewer: 需要同步的Mars3d实例对象(如果未创建实例则不传)， state: 是否开启同步功能（默认true,除初始化传入，后续通过setStateById， enableById， closeById更改state）}]
 * @param    viewer   Mars3d实例对象，新的viewer使用这个实例对象的option进行构建,并与该viewer的相机同步
 * 
 * @function enableById                 通过id指定对应的viewer开启同步
 * @function closeById                  通过id指定对应的viewer关闭同步
 * @function setStateById               通过id指定对应的viewer同步状态（开启/关闭）
 * @function enableAll                  开启所有viewer同步功能
 * @function closeAll                   关闭所有viewer同步功能
 * @function getViewDataById            通过id查询对应的viewer数据
 * @function addViewerById              通过id创建的viewer
 * @function destroyViewerById          删除id对应的viewer(dom与相关的同步事件都会删除)
 * @function destroy                    清空实例（执行后，清空所有数据与同步相关的相机事件，但并不会清空dom和创建的viewer）
 *      
 * @returns  BQGIS_synchronization
 */

export function BQGIS_initSynchronization({
    viewers,
    viewer
}) {
    let synchronization = new BQGIS_synchronization({
        viewers,
        viewer
    });
    return synchronization;
}


function BQGIS_synchronization({
    viewers,
    viewer
}) {
    this.viewer = viewer
    this.viewers = viewers.map(item => this.createViewer(item))
}

BQGIS_synchronization.prototype.createViewer = function ({
    id,
    viewer,
    option,
    state = true
}) {
    const v = (viewer || viewer instanceof mars3d.Map) ? viewer : new mars3d.Map(id, option || this.viewer.getCurrentOptions())
    v.camera.percentageChanged = 0.01
    this.cameraSynchronization(this.viewers, v)
    return {
        id: id || v.container.getAttribute('id'),
        viewer: v,
        state,
        event: state ? this.createEvent(v) : null
    }
}

/**
 * 创建可同步的 mars3d 实例
 * @param    id              dom与mars3d实例的id (必传)
 * @param    parent          父级dom(创建的窗口在哪个dom下) (必传)
 * @param    style           dom的css信息 (必传)
 * @param    option          option 创建 mars3d实例的参数信息(可选，不传时使用this.viewer的配置)
 * @param    state           是否开启同步 (可选，默认true)
 * 
 * @returns  BQGIS_synchronization
 */
BQGIS_synchronization.prototype.addViewerById = function (id, parent, style, option, state = true) {
    this.createDom(id, parent, style)
    const data = this.createViewer({
        id,
        option,
        state
    })
    this.viewers.push(data)
    return data
}

BQGIS_synchronization.prototype.createDom = function (id, parent, style) {
    const dom = mars3d.DomUtil.create("div", "", parent)
    dom.setAttribute("id", id)
    Object.assign(dom.style, style)
}

BQGIS_synchronization.prototype.destroyViewerById = function (id) {
    const index = this.viewers.findIndex(viewerData => viewerData.id === id)
    this.closeById(id)
    this.viewers.splice(index, 1)
    const dom = document.getElementById(id)
    dom.remove()
}

BQGIS_synchronization.prototype.createEvent = function (viewer) {
    return viewer.camera.changed.addEventListener(() => {
        this.viewers.forEach(targetViewer => {
            if(targetViewer && targetViewer.event && viewer !== targetViewer.viewer){
                targetViewer.event()
                targetViewer.event = null
            }
        });
        this.viewers.forEach(targetViewer => {
            this.cameraSynchronization(viewer, targetViewer)
        })
        this.viewers.forEach(targetViewer => {
            if(targetViewer && targetViewer.state && viewer !== targetViewer.viewer){
                if(targetViewer.time !== null){
                    clearTimeout(targetViewer.time);
                }
                targetViewer.time = setTimeout(() => {
                    targetViewer.event = this.createEvent(targetViewer.viewer)
                },300)
            }
        })
    })
}


BQGIS_synchronization.prototype.setStateById = function (id, state) {
    if (state) {
        this.enableById(id)
    } else {
        this.closeById(id)
    }
}

BQGIS_synchronization.prototype.enableAll = function (id) {
    this.viewers.forEach(current => {
        if (!current.state) {
            current.state = true
            current.event = this.createEvent(current.viewer)
        }
    })
}

BQGIS_synchronization.prototype.closeAll = function (id) {
    this.viewers.forEach(current => {
        if (current.state) {
            current.state = false
            current.event()
            current.event = null
        }
    })
}

BQGIS_synchronization.prototype.enableById = function (id) {
    const current = this.getViewDataById(id)
    if (!current || current.state) return
    current.state = true
    current.event = this.createEvent(current.viewer)
}

BQGIS_synchronization.prototype.closeById = function (id) {
    const current = this.getViewDataById(id)
    if (!current || !current.state) return
    current.state = false
    current.event()
    current.event = null
}

BQGIS_synchronization.prototype.getViewDataById = function (id) {
    return this.viewers.find(viewerData => viewerData.id === id)
}

BQGIS_synchronization.prototype.cameraSynchronization = function (viewer, targetViewer) {
    if (targetViewer.viewer && targetViewer.viewer !== viewer && targetViewer.state) {
        // setCurrentViewer(viewer)
        if (viewer.scene.mode != 2 && targetViewer.viewer.scene.mode != 2) {
            let lng = viewer.camera.positionCartographic.longitude;
            let lat = viewer.camera.positionCartographic.latitude;
            let alt = viewer.camera.positionCartographic.height;
            let heading = viewer.camera.heading
            let pitch = viewer.camera.pitch
            let roll = viewer.camera.roll
            targetViewer.viewer.camera.setView({
                destination: Cesium.Cartesian3.fromRadians(lng, lat, alt),
                orientation: {
                    heading,
                    pitch,
                    roll
                }
            })
        } else if (viewer.scene.mode != 2 && targetViewer.viewer.scene.mode === 2) {
           const { lng, lat, alt} = viewer.getCenter()
            let height = viewer.camera.positionCartographic.height;
            targetViewer.viewer.camera.setView({
                destination: Cesium.Cartesian3.fromDegrees(lng, lat, height),
            })
        } else if (viewer.scene.mode === 2 && targetViewer.viewer.scene.mode === 2) {
            let lng = viewer.camera.positionCartographic.longitude;
            let lat = viewer.camera.positionCartographic.latitude;
            let alt = viewer.camera.positionCartographic.height;
            targetViewer.viewer.camera.setView({
                destination: Cesium.Cartesian3.fromRadians(lng, lat, alt),
            });
        } else if (viewer.scene.mode === 2 && targetViewer.viewer.scene.mode != 2) {
            let lng = viewer.camera.positionCartographic.longitude;
            let lat = viewer.camera.positionCartographic.latitude;
            let alt = viewer.camera.positionCartographic.height;
            targetViewer.viewer.camera.setView({
                destination: Cesium.Cartesian3.fromRadians(lng, lat, alt),
            });
            // let heading = targetViewer.viewer.camera.heading
            // let pitch = targetViewer.viewer.camera.pitch
            // let roll = targetViewer.viewer.camera.roll
            // targetViewer.viewer.camera.setView({
            //     destination: Cesium.Cartesian3.fromRadians(lng, lat, alt),
            //     orientation: {
            //         heading,
            //         pitch,
            //         roll
            //     }
            // });
        }
    }
}

BQGIS_synchronization.prototype.destroy = function () {
    this.viewers.forEach(viewerData => { // 卸载事件
        if (viewerData.event) {
            viewerData.event()
            viewerData.event = null
        }
    })
    this.viewers = null
    this.option = null
}